﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;

namespace WebCamera.WebSocket
{
    public class FileCamera : WebSocketManagerMiddleware.WebSocketHandler
    {
        private fMP4.fMP4Callback _callback;
        public FileCamera(WebSocketConnectionManager webSocketConnectionManager) 
            : base(webSocketConnectionManager)
        {
            _callback = MP4CallbackAsync;
        }

        private async void MP4CallbackAsync(byte[] data, int len, IntPtr userData)
        {
                KeyValuePair<IntPtr, System.Net.WebSockets.WebSocket> info;
                lock (_sockets)
                {
                    info = _sockets.FirstOrDefault(p => p.Key == userData);
                }

                if (info.Value != null)
                {
                    try
                    {
                        if (info.Value.State == WebSocketState.Open)
                        {
                            await info.Value.SendAsync(new ArraySegment<byte>(array: data, 0, len), WebSocketMessageType.Binary, true, CancellationToken.None);
                        }
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(e);
                        await info.Value.CloseAsync(WebSocketCloseStatus.Empty, "", CancellationToken.None);
                    }
                }
        }
        private Dictionary<IntPtr, System.Net.WebSockets.WebSocket> _sockets = new Dictionary<IntPtr, System.Net.WebSockets.WebSocket>();
        protected override void StartCamera(System.Net.WebSockets.WebSocket socket, string chn, string args)
        {
            bool bMP4 = false;
            IntPtr fMP4Handle = IntPtr.Zero;
            if (!string.IsNullOrEmpty(args))
            {
                bMP4 = true;
                fMP4Handle = fMP4.fMP4_CreateH264();
                fMP4.fMP4_SetCallback(fMP4Handle, _callback, fMP4Handle);
                lock (_sockets)
                {
                    _sockets.Add(fMP4Handle, socket);
                }
            }
            Task.Run(async () =>
            {
                try
                {
                    var buffer = new byte[65535];
                    using (var file = File.Open(chn, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        while (socket.State == WebSocketState.Open)
                        {
                            var len = file.Read(buffer, 0, buffer.Length);
                            if (len == 0)
                                break;

                            if (bMP4 && fMP4Handle != IntPtr.Zero)
                            {
                                fMP4.fMP4_WriteH264(fMP4Handle, buffer, len);
                            }
                            else
                            {
                                await socket.SendAsync(new ArraySegment<byte>(buffer, 0, len), WebSocketMessageType.Binary, true, CancellationToken.None);
                            }
                            // 太快了, 等待一会
                            Thread.Sleep(50);
                        }
                    }
                }
                catch (Exception e)
                {
                    Trace.WriteLine(e);
                }
            });
        }

        protected override void StopCamera(System.Net.WebSockets.WebSocket socket)
        {
            
        }
    }
}
